XieYang-blog

在CI上使用git subtree强制推送代码到gh-pages

最近在前端持续集成上面遇到一个问题,在百度上查了无数资料,无解!!也可能是我搜索姿势不对… -_-
但是当我尝试在google上搜索时,很快得到了答案。
写这段话的目的不是为了黑百度,扬谷歌,望勿借题发挥。至于我的目的,你们自行脑补。😄

前端持续集成,目前流行的平台 circleCI、travis ci等,两者的区别不多介绍,大家可以自行搜索。

CI的配置也不多做介绍,有兴趣的可以去他们的官网。

我用CI做了个发布demo的测试,主要流程是当我提交代码到github仓库时,CI会自动拉取代码或者说clone最新代码到虚拟机上,然后CI会找到仓库里的.yml(CI的配置文件),并依次执行配置文件里面的预先定义好的代码。

配置文件里面的代码流程是利用webpack编译一个静态的demo出来,编译输出地址为.examples,然后将examples里面的静态文件推送到gh-pages分支。

代码如下:

注意:${...}里面的内容为CI变量,这个可以在CI平台的设置里面预先定义好,这里不过多讨论。
为什么要在用变量,而不直接写在配置文件里?如果是私有仓库,则可以这么做;如果是公开仓库,那你的密码会被所有人看见。

1
2
3
4
5
6
git remote rm origin
git remote add orgin "https://${username}:${password}@github.com/${username}/${repositoryName}.git"

yarn webpack --config build/webpack.config.demo

git subtree push -P examples github gh-pages

执行git remote rm origin的原因是CI在clone项目的时候使用的是如下命令:

1
git clone --depth=50 --branch=master https://github.com/${username}/${repositoryName}.git ${username}/${repositoryName}

可以清楚地看到这只是一个普通的clone仓库代码,里面没有包含用户名和密码,这样就不能直接push代码到github仓库了,所以要做一下修改。

因为这些流程是在CI的虚拟机里面完成的,我们不能也无法在push代码的时候输入用户名和密码,所以要把仓库的用户名(username)和密码(password)写到仓库地址中去。

如下:

1
git remote add orgin "https://${username}:${password}@github.com/${username}/${repositoryName}.git"

这样我们就可以把webpack编译好的demo的静态文件后直接push到gh-pages分支了。

当然还有另外的解决方案,如:

  1. 在虚拟机里面设置全局的用户名和密码。
  2. token来代替password代替,这样自己的密码被保护得更好,只需一个token就行。
1
yarn webpack --config build/webpack.config.demo

这句代码就是用webpack打包静态文件,输出到./examples文件夹下。

1
git subtree push -P examples github gh-pages

这句代码是把examples文件夹下的demo静态文件push到gh-pages分支。

执行到这里,问题来了,CI虚拟机报错:

1
2
3
4
5
6
 ! [rejected]        ******299ab2694e13f437654jb8561c98****** -> gh-pages (fetch first)
error: failed to push some refs to 'https://[secure]@github.com/oceanxy/react-tabllist.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.

依照问题的提示,在push代码之前执行git pull

但是这样做又会包另外一个错误:

1
2
3
4
5
 ! [rejected]        ******299ab2694e13f437654jb8561c98****** -> gh-pages (non-fast-forward)
error: failed to push some refs to 'https://oceanxy:[secure]@github.com/oceanxy/react-tabllist.git'
hint: Updates were rejected because a pushed branch tip is behind its remote
hint: counterpart. Check out this branch and integrate the remote changes
hint: (e.g. 'git pull ...') before pushing again.

最终换了下思路,强制推送新的静态文件到gh-pages分支

但是我使用的是git subtree,它没有强制推送 –force 这个选项,最终在google里搜索得到如下方法:

1
git push github `git subtree split --prefix examples master`:gh-pages --force

然后提交代码到github,CI自动拉去最新代码及配置文件开始跑虚拟机,等待…success!

最终跑通的流程代码如下:

1
2
3
4
5
6
git remote rm origin
git remote add orgin "https://${username}:${password}@github.com/${username}/${repositoryName}.git"

yarn webpack --config build/webpack.config.demo

git push github `git subtree split --prefix examples master`:gh-pages --force
🐶 您的支持将鼓励我继续创作 🐶